﻿namespace Calendar
{
    using System;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;

    public class SelectionTool : ITool
    {
        private EventHandler _Complete;
        private Calendar.DayView dayView;
        private TimeSpan delta;
        private TimeSpan length;
        private Mode mode;
        private DateTime startDate;

        public event EventHandler Complete
        {
            add
            {
                EventHandler handler2;
                EventHandler complete = this._Complete;
                do
                {
                    handler2 = complete;
                    EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value);
                    complete = Interlocked.CompareExchange<EventHandler>(ref this._Complete, handler3, handler2);
                }
                while (complete != handler2);
            }
            remove
            {
                EventHandler handler2;
                EventHandler complete = this._Complete;
                do
                {
                    handler2 = complete;
                    EventHandler handler3 = (EventHandler) Delegate.Remove(handler2, value);
                    complete = Interlocked.CompareExchange<EventHandler>(ref this._Complete, handler3, handler2);
                }
                while (complete != handler2);
            }
        }

        private Mode GetMode(MouseEventArgs e)
        {
            Calendar.DayView.AppointmentView view = null;
            bool flag = false;
            if (this.dayView.SelectedAppointment != null)
            {
                if (this.dayView.appointmentViews.ContainsKey(this.dayView.SelectedAppointment))
                {
                    view = this.dayView.appointmentViews[this.dayView.SelectedAppointment];
                    flag = true;
                }
                else if (this.dayView.longappointmentViews.ContainsKey(this.dayView.SelectedAppointment))
                {
                    view = this.dayView.longappointmentViews[this.dayView.SelectedAppointment];
                    flag = true;
                }
                if (flag)
                {
                    Rectangle rectangle = view.Rectangle;
                    Rectangle rectangle2 = view.Rectangle;
                    Rectangle rectangle3 = view.Rectangle;
                    Rectangle rectangle4 = view.Rectangle;
                    rectangle2.Y = rectangle2.Bottom - 5;
                    rectangle2.Height = 5;
                    rectangle.Height = 5;
                    rectangle3.Width = 5;
                    rectangle4.X += rectangle4.Width - 5;
                    rectangle4.Width = 5;
                    if (rectangle.Contains(e.Location))
                    {
                        return Mode.ResizeTop;
                    }
                    if (rectangle2.Contains(e.Location))
                    {
                        return Mode.ResizeBottom;
                    }
                    if (rectangle4.Contains(e.Location))
                    {
                        return Mode.ResizeRight;
                    }
                    if (rectangle3.Contains(e.Location))
                    {
                        return Mode.ResizeLeft;
                    }
                    return Mode.Move;
                }
            }
            return Mode.None;
        }

        public void MouseDown(MouseEventArgs e)
        {
            if (this.dayView.SelectedAppointmentIsNew)
            {
                this.dayView.RaiseNewAppointment();
            }
            if (this.dayView.CurrentlyEditing)
            {
                this.dayView.FinishEditing(false);
            }
            this.mode = this.GetMode(e);
            if (this.dayView.SelectedAppointment != null)
            {
                DateTime timeAt = this.dayView.GetTimeAt(e.X, e.Y);
                this.delta = (TimeSpan) (this.dayView.SelectedAppointment.StartDate - timeAt);
            }
            else
            {
                this.delta = TimeSpan.Zero;
            }
            this.length = TimeSpan.Zero;
        }

        public void MouseMove(MouseEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }
            Appointment selectedAppointment = this.dayView.SelectedAppointment;
            Rectangle trueRectangle = this.dayView.GetTrueRectangle();
            Rectangle fullDayApptsRectangle = this.dayView.GetFullDayApptsRectangle();
            if ((trueRectangle.Contains(e.Location) || fullDayApptsRectangle.Contains(e.Location)) && ((selectedAppointment != null) && !selectedAppointment.Locked))
            {
                if (e.Button != MouseButtons.Left)
                {
                    switch (this.GetMode(e))
                    {
                        case Mode.ResizeTop:
                        case Mode.ResizeBottom:
                            if (!selectedAppointment.AllDayEvent)
                            {
                                this.dayView.Cursor = Cursors.SizeNS;
                            }
                            return;

                        case Mode.ResizeLeft:
                        case Mode.ResizeRight:
                            if (selectedAppointment.AllDayEvent)
                            {
                                this.DayView.Cursor = Cursors.SizeWE;
                            }
                            return;

                        case Mode.Move:
                            this.dayView.Cursor = Cursors.Default;
                            return;
                    }
                }
                else
                {
                    DateTime timeAt = this.dayView.GetTimeAt(e.X, e.Y);
                    switch (this.mode)
                    {
                        case Mode.ResizeTop:
                            if ((timeAt < selectedAppointment.EndDate) && (selectedAppointment.StartDate.Day == timeAt.Day))
                            {
                                selectedAppointment.StartDate = timeAt;
                                this.dayView.Invalidate();
                                this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                            }
                            return;

                        case Mode.ResizeBottom:
                            if ((timeAt > selectedAppointment.StartDate) && (selectedAppointment.EndDate.Day == timeAt.Day))
                            {
                                selectedAppointment.EndDate = timeAt;
                                this.dayView.Invalidate();
                                this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                            }
                            return;

                        case Mode.ResizeLeft:
                            if (timeAt.Date < selectedAppointment.EndDate.Date)
                            {
                                selectedAppointment.StartDate = timeAt.Date;
                                this.dayView.Invalidate();
                                this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                            }
                            return;

                        case Mode.ResizeRight:
                            if (timeAt.Date >= selectedAppointment.StartDate.Date)
                            {
                                selectedAppointment.EndDate = timeAt.Date.AddDays(1.0);
                                this.dayView.Invalidate();
                                this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                            }
                            return;

                        case Mode.Move:
                            if (selectedAppointment.AllDayEvent || !trueRectangle.Contains(e.Location))
                            {
                                if (fullDayApptsRectangle.Contains(e.Location))
                                {
                                    int days = timeAt.Add(this.delta).Subtract(selectedAppointment.StartDate).Days;
                                    if ((days != 0) && (selectedAppointment.StartDate.AddDays((double) days) > this.dayView.StartDate))
                                    {
                                        selectedAppointment.StartDate = selectedAppointment.StartDate.AddDays((double) days);
                                        selectedAppointment.EndDate = selectedAppointment.EndDate.AddDays((double) days);
                                        this.dayView.Invalidate();
                                        this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                                    }
                                }
                                return;
                            }
                            timeAt = timeAt.Add(this.delta);
                            if (!(this.length == TimeSpan.Zero))
                            {
                                DateTime time2 = timeAt.Add(this.length);
                                if (time2.Day == timeAt.Day)
                                {
                                    selectedAppointment.StartDate = timeAt;
                                    selectedAppointment.EndDate = time2;
                                    this.dayView.Invalidate();
                                    this.dayView.RaiseAppointmentMove(new AppointmentEventArgs(selectedAppointment));
                                }
                                return;
                            }
                            this.startDate = selectedAppointment.StartDate;
                            this.length = (TimeSpan) (selectedAppointment.EndDate - this.startDate);
                            return;
                    }
                }
            }
        }

        public void MouseUp(MouseEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }
            if ((e.Button == MouseButtons.Left) && (this._Complete != null))
            {
                this._Complete(this, EventArgs.Empty);
            }
            this.dayView.RaiseSelectionChanged(EventArgs.Empty);
            this.mode = Mode.Move;
            this.delta = TimeSpan.Zero;
        }

        public void Reset()
        {
            this.length = TimeSpan.Zero;
            this.delta = TimeSpan.Zero;
        }

        public Calendar.DayView DayView
        {
            get
            {
                return this.dayView;
            }
            set
            {
                this.dayView = value;
            }
        }

        private enum Mode
        {
            ResizeTop,
            ResizeBottom,
            ResizeLeft,
            ResizeRight,
            Move,
            None
        }
    }
}

